/*
 * Contains lobby screen code
 */

#include <string.h>
#include <allegro.h>
#include "main.h"
#include "network.h"
#include "player.h"
#include "main.h"
#include "bailout.h"
#include "game.h"
#include "chat.h"
#include "colors.h"

#define INQUIRY_INTERVAL (FPS/3)
#define HUGE_INQUIRY_INTERVAL (FPS*5)

CtoSmessage netmessage; // For communications to server
StoCmessage received;  // For communications to server
int inquiry_countdown; // Ticks until next attempt to send pending requests to server
int ready; // indicates this client ready status
char nickname [MAX_NAMELEN]; // my nickname
	
/* send a friendly hello msg to server */
void send_hello ()
{
	netmessage.type = CtoS_HELLO;
	strcpy (netmessage.nickname, nickname);
	send_CtoSmessage (&netmessage);
}

/* send player registration request  [NEEDS REDESIGN in later versions] */
void send_player ()
{
	netmessage.type = CtoS_LOBBY_ADDPLAYER;
	strcpy (netmessage.data.nickname, nickname);
	netmessage.data.character = 2;
	send_CtoSmessage (&netmessage);
}

static void send_chat(const char* text) {
	CtoSmessage msg;
	msg.type = CtoS_CHAT;
	strcpy (msg.line, text);
	send_CtoSmessage(&msg);
}

// prompts the user to input a server host name and a nickname
void prompt_input (const char* request, char* input, const char* presetting)
{
	strcpy (input, presetting);
	char* inptr = input + strlen(presetting);
	int keypress = 0;
	
	do {		
		acquire_screen ();
		clear_bitmap (screen);
		textprintf_ex(screen, font, 20, SCREEN_H/2, LOBBY_COL, 0, "%s %s", request, input);
		release_screen ();
		
		keypress = readkey();
		if ((keypress >> 8) == KEY_BACKSPACE) {
			if (inptr > input) *--inptr = '\0';
		} else {
			*inptr++ = keypress & 0xFF;
		}
	} while ((keypress >> 8) != KEY_ENTER);
	
	*(inptr-1) = '\0';
}

void lobby_init ()
{
	char servername [MAX_NAMELEN];
	memset (servername, 0, sizeof(servername));
	memset (nickname, 0, sizeof(nickname));
	prompt_input ("Enter server name:", servername, "localhost");
	prompt_input ("Enter your nickname:", nickname, "");

	show_mouse (screen);
	
	network_init (servername);
	send_hello ();
	send_player ();

	chat_init ();
	
	inquiry_countdown = HUGE_INQUIRY_INTERVAL;
	ready = 0;
}

void lobby_cleanup ()
{
	show_mouse (NULL);
}

// true if client has been registered on server
int server_has_my_client ()
{
	for (int i = 0; i < MAX_CLIENTS; i++) if (peer[i].uid == my_uid) return 1;
	return 0;
}

static int my_player ()
{
	for (int i = 0; i < MAX_PLAYERS; i++) 
		if ((*player[i].data.nickname != 0) && (peer[owner[i]].uid == my_uid)) return i;
	return -1;
}

// true if player has been registered on server [NEEDS REDESIGN in later versions]
int server_has_my_player ()
{
	return my_player() != -1;
}

void lobby_update ()
{
	inquiry_countdown --;
	
	if (inquiry_countdown <= 0) {
		inquiry_countdown = INQUIRY_INTERVAL;
		// fire bits of request to server
		if (!server_has_my_client()) send_hello (); else
		if (!server_has_my_player()) send_player (); else
		inquiry_countdown = HUGE_INQUIRY_INTERVAL; // server has all data, wait longer
	}
	
	receive_StoCmessage (&received);
	while (received.type != StoC_NOMSG) {
		switch (received.type) {
		
		case StoC_LOBBY_CLIENTREADY:
			peer[received.clientidx].ready = 1;
			break;
		
		case StoC_LOBBY_CLIENTNOTREADY:
			peer[received.clientidx].ready = 0;
			break;
		
		case StoC_LOBBY_SEEDGAME:
			game_seed (received.seed);
			break;
		
		case StoC_LOBBY_STARTGAME:
			controlled_player = my_player (); // set var in game.h
			#if TOWERHACK_DEBUG
			fprintf (stderr, "[Lobby] I control player %d.\n", controlled_player);
			#endif
			change_state (STATE_GAME); // players are ready, go in-game
			return; // get out of here to be safe from gamestate-consistency errors
		
		case StoC_CHAT:
			chat_receive (received.line);
			break;
		
		default:
			bailout ("sds", "Received unidentified message type ", received.type, " from server.");
			break;
			
		}
		
		receive_StoCmessage (&received);
	} 
	
	if (keypressed ()) {
		char* line;
		if ((line = chat_input()) != NULL) {
			send_chat (line);
			if (strncmp(line, "ready", 5) == 0) {
				ready = !ready;
				if (ready) {
					netmessage.type = CtoS_LOBBY_READY;
					send_CtoSmessage (&netmessage);
				} else {
					netmessage.type = CtoS_LOBBY_NOTREADY;
					send_CtoSmessage (&netmessage);
				}
			}
		}		
	}
}

void lobby_draw ()
{
	int i;
	
	acquire_bitmap(buffer);
	clear_bitmap (buffer);
	
	// border
	rectfill(buffer, 5, 5, SCREEN_W-5, SCREEN_H-5, LOBBY_COL);
	rectfill(buffer, 15, 15, SCREEN_W-15, SCREEN_H-15, 0);
	
	// clients border
	rectfill(buffer, 20, 30, SCREEN_W/2-10, SCREEN_H-20, LOBBY_COL);
	rectfill(buffer, 25, 35, SCREEN_W/2-15, SCREEN_H-25, 0);
	
	// players border
	rectfill(buffer, SCREEN_W/2+10, 30, SCREEN_W-20, SCREEN_H-20, LOBBY_COL);
	rectfill(buffer, SCREEN_W/2+15, 35, SCREEN_W-25, SCREEN_H-25, 0);
	
	textout_centre_ex(buffer, font, "Lobby", SCREEN_W/2, 20, LOBBY_COL_BRIGHT, 0);
	textout_centre_ex(buffer, font, "Clients", SCREEN_W/4, 40, LOBBY_COL_BRIGHT, 0);
	textout_centre_ex(buffer, font, "Players", SCREEN_W*3/4, 40, LOBBY_COL_BRIGHT, 0);
	
	for (i = 0; i < MAX_CLIENTS; i++) {
		if (*peer[i].nickname == 0) break;
		textprintf_ex(buffer, font, 30, 50 + i * 25, LOBBY_COL_BRIGHT, 0, "%d: %s", i, peer[i].nickname);
		if (peer[i].ready)
			rectfill (buffer, SCREEN_W/2-35, 50 + i * 25, SCREEN_W/2-25, 60 + i * 25, LOBBY_COL_BRIGHT);
		else
			rect (buffer, SCREEN_W/2-35, 50 + i * 25, SCREEN_W/2-25, 60 + i * 25, LOBBY_COL_BRIGHT);
	}

	for (i = 0; i < MAX_PLAYERS; i++) {
		if (*player[i].data.nickname == 0) break;
		textprintf_ex(buffer, font, SCREEN_W/2+30, 50 + i * 25, LOBBY_COL_BRIGHT, 0, "%s (%s)", player[i].data.nickname, peer[owner[i]].nickname);
	}

	chat_display_messages ();
	chat_display_input ();
	
	release_bitmap(buffer);
}

